import utils

import os
import math
from chapter import section3

# 知识点:
# 4.4  文件I/O
# 4.5 异常

# 4.8 异步IO

# 导入 package 下的 module 是:from…import 语句
from pkg_test.classroom_test import test_classroom

# 而不是:
# import pkg_test.classroom_test.test_classroom

# 4.1Python 模块
# Python 模块(Module)，是一个 Python 文件，以 .py 结尾，包含了 Python 对象定义和Python语句。
# 模块让你能够有逻辑地组织你的 Python 代码段。
# 把相关的代码分配到一个模块里能让你的代码更好用，更易懂。

# 为了编写可维护的代码，我们把很多函数分组，分别放到不同的文件里，这样，每个文件包含的代码就相对较少，
# 很多编程语言都采用这种组织代码的方式。在Python中，一个.py文件就称之为一个模块（Module）

# 使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中，因此，我们自己在编写模块时，不必考虑名字会与其他模块冲突

var = utils.get_current_time()
print("===time==", var)

# 4.2 Python中的包
# 如果不同的人编写的模块名相同怎么办？为了避免模块名冲突，Python又引入了按目录来组织模块的方法，称为包（Package）。
# 比如现在我的 chapter 就是一个包,包含各个 section 的module,
# 注意 chapter包目录下面有一个__init__.py的文件，这个文件是必须存在的，否则，Python就把这个目录当成普通目录，而不是一个包。
# __init__.py可以是空文件，也可以有Python代码，因为__init__.py本身就是一个模块，而它的模块名就是chapter。

name = test_classroom.get_class_name()
print("===name==", name)

# 4.3 全局变量
# 如果要给函数内的全局变量赋值，必须使用 global 语句。
# global VarName 的表达式会告诉 Python， VarName 是一个全局变量，这样 Python 就不会在局部命名空间里寻找这个变量了。

# dir()函数
# dir() 函数一个排好序的字符串列表，内容是一个模块里定义过的名字。
# 返回的列表容纳了在一个模块里定义的所有模块，变量和函数
# content = dir(test_classroom)  # 打开注释可测试
# print(content)   # 打开注释可测试

# content = dir(math)   # 打开注释可测试
# print(content)   # 打开注释可测试

# content = dir(section3)   # 打开注释可测试
# print(content)   # 打开注释可测试

# globals() 和 locals() 函数
# 根据调用地方的不同，globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字。
#
# 如果在函数内部调用 locals()，返回的是所有能在该函数里访问的命名。
#
# 如果在函数内部调用 globals()，返回的是所有在该函数里能访问的全局名字。
#
# 两个函数的返回类型都是字典。所以名字们能用 keys() 函数摘取。

# reload() 函数

# 当一个模块被导入到一个脚本，模块顶层部分的代码只会被执行一次。
#
# 因此，如果你想重新执行模块里顶层部分的代码，可以用 reload() 函数。该函数会重新导入之前导入过的模块

# 4.4 Python 文件I/O
print("-------------文件I/O------------------")

# 4.4.1 打印到屏幕
print(" 通过使用 print 打印输出")

# 4.4.2 读取键盘输入
# 使用 input 和 raw_input
# str_test = input("请输入：")  # 打开注释可测试
# str_test = raw_input("请输入：")
# print("你输入的内容是: ", str)   # 打开注释可测试

# 4.4.3 打开和关闭文件
foo = open("/PythonSpace/gitAddress.txt", "r")
print("文件名: ", foo.name)
print("是否已关闭 : ", foo.closed)
print("访问模式 : ", foo.mode)
result = foo.read(50)
print("文件内容: ", result)
# 查找当前位置
position = foo.tell()
print("当前文件位置 : ", position)

# 把指针再次重新定位到文件开头
position = foo.seek(0, 0)
str2 = foo.read(4)
print("重新读取字符串 : ", str2)
foo.close()
print("是否已关闭 : ", foo.closed)

my_writer = open("/PythonSpace/python_write_test.txt", "a+")
# 先追加一个换行,
my_writer.write("\n")
my_writer.write("this is bench test")
# write()方法不会在字符串的结尾添加换行符('\n')：
# my_writer.write("this is bench test2")
my_writer.close()
#
# 为了保证无论是否出错都能正确地关闭文件，我们可以使用try ... finally来实现：
# try:
#     f = open('/path/to/file', 'r')
#     print(f.read())
# finally:
#     if f:
#         f.close()

# h或者直接使用Python引入了with语句,和前面的try ... finally是一样的，但是代码更佳简洁，并且不必调用f.close()方法。
with open("/PythonSpace/gitAddress.txt", "r") as file:
    print("use with 语句输出--------\n", file.read())
    print("---------with 语句输出--end---------")

#  使用 realline()
#

print("---------readlines 语句输出---------")
with open("/PythonSpace/gitAddress.txt", "r") as file_new:
    for line in file_new.readlines():
        print(line.strip())  # 把末尾的'\n'删掉
print("---------readlines 语句输出-end--------")

# 二进制文件
# 字符编码

# StringIO和BytesIO是在内存中操作str和bytes的方法，使得和读写文件具有一致的接口。
# from io import StringIO
#  f = StringIO()
#  f.write('hello')


# from io import BytesIO
# f = BytesIO()
#  f.write('中文'.encode('utf-8'))

# 4.4.4
# 重命名和删除文件
# Python的os模块提供了帮你执行文件处理操作的方法，比如重命名和删除文件


# 如果是posix，说明系统是Linux、Unix或Mac OS X，如果是nt，就是Windows系统。
print("os type== ", os.name)  # 操作系统类型
# 详细的系统信息 注意uname()函数在Windows上不提供，也就是说，os模块的某些函数是跟操作系统相关的。
print("os uname== ", os.uname())

# 查看当前目录的绝对路径:
print("os abspath== ", os.path.abspath('.'))
#

# 重命名文件test1.txt到test2.txt。
# os.rename("test1.txt", "test2.txt")

# os.remove(file_name)

# os模块有许多方法能帮你创建，删除和更改目录
# os.mkdir("newdir")

# 可以用chdir()方法来改变当前的目录。chdir()方法需要的一个参数是你想设成当前目录的目录名称。
# os.chdir("newdir")

# getcwd()方法显示当前的工作目录。
print("getcwd ", os.getcwd())

# rmdir()方法删除目录，目录名称以参数传递。
# os.rmdir('dirname')

# 4.4.5
# Python File(文件) 方法
# Python open() 方法用于打开一个文件，并返回文件对象，在对文件进行处理过程都需要使用到这个函数，如果该文件无法被打开，会抛出 OSError。
# 注意：使用 open() 方法一定要保证关闭文件对象，即调用 close() 方法。
#  file 对象常用的函数：

# 1.
#
# file.close() 关闭文件。关闭后文件不能再进行读写操作。
# 2.
# file.flush() 刷新文件内部缓冲，直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入
# 3.
# file.fileno() 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上
# 4.
#
# file.isatty() 如果文件连接到一个终端设备返回 True，否则返回 False。
# 5
#
# file.next()返回文件下一行。
# 6.
#
# file.read([size])  从文件读取指定的字节数，如果未给定或为负则读取所有。
# 7.
#
# file.readline([size]) 读取整行，包括 "\n" 字符。
# 8.
#
# file.readlines([sizeint]) 读取所有行并返回列表，若给定sizeint>0，则是设置一次读多少字节，这是为了减轻读取压力
# 9.
# file.seek(offset[, whence])  设置文件当前位置
# 10.
#
# file.tell() 返回文件当前位置。
# 11.
#
# file.truncate([size])  截取文件，截取的字节通过size指定，默认为当前文件位置
# 12.
#
# file.write(str)  将字符串写入文件，返回的是写入的字符长度。
# 13.
# file.writelines(sequence) 向文件写入一个序列字符串列表，如果需要换行则要自己加入每行的换行符

# 4.5
# Python 异常处理
# try/except语句用来检测try语句块中的错误，从而让except语句捕获异常信息并处理。
# 语法：
#  以下为简单的try....except...else的语法：
# try:
# <语句>        #运行别的代码
# except <名字>：
# <语句>        #如果在try部份引发了'name'异常
# except <名字>，<数据>:
# <语句>        #如果引发了'name'异常，获得附加的数据
# else:
# <语句>        #如果没有异常发生


# foo = open("/PythonSpace/gitAddress.txt", "r")
# print("文件名: ", foo.name)
try:
    fh = open("/PythonSpace/python_write_test.txt", "a+")
    fh.write("\n")
    fh.write("这是一个测试文件，用于测试异常!!")
except IOError:
    print("Error: 没有找到文件或读取文件失败")
else:
    print("内容写入文件成功")
    fh.close()

#     try-finally 语句
# try:
# <语句>
# finally:
# <语句>    #退出try时总会执行
# raise


try:
    fh = open("/PythonSpace/python_write_test.txt", "a+")
    try:
        fh.write("这是一个测试文件，用于测试异常!! bench test ")
    finally:
        print("关闭文件")
        fh.close()
except IOError:
    print("Error: 没有找到文件或读取文件失败")


#     触发异常
# 我们可以使用raise语句自己触发异常
#
# raise语法格式如下：
# raise [Exception [, args [, traceback]]]


def set_age(params):
    if params < 0:
        raise Exception("params can't < 0")


# 使用try...except捕获错误还有一个巨大的好处，就是可以跨越多层调用，
# 比如函数main()调用foo()，foo()调用bar()，结果bar()出错了，这时，只要main()捕获到了，就可以处理

# 4.6
# os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示
# TODO
# 4.7
# Python 内置函数
# TODO


